package com.kingint.web.portal.serve.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kingint.mbg.bas.entity.BasHotel;
import com.kingint.mbg.bas.entity.BasRepairGoods;
import com.kingint.mbg.bas.entity.BasWarrantyItems;
import com.kingint.mbg.bas.mapper.BasHotelMapper;
import com.kingint.mbg.data.entity.DataHouseServices;
import com.kingint.mbg.dto.department.DepartmentRepairFront;
import com.kingint.mbg.dto.department.DepartmentRepairParam;
import com.kingint.mbg.dto.MemberReturn;
import com.kingint.mbg.dto.department.StepBean;
import com.kingint.mbg.ser.entity.*;
import com.kingint.mbg.ser.mapper.*;
import com.kingint.mbg.sys.entity.UmsMember;
import com.kingint.mbg.sys.mapper.UmsMemberMapper;
import com.kingint.web.admin.base.service.BasOrderTypeHotelTimeService;
import com.kingint.web.admin.serve.service.SerReceiveWorkMiddleService;
import com.kingint.web.portal.base.service.WorkOrderTypeService;
import com.kingint.web.portal.data.service.DataHouseServicesService;
import com.kingint.web.portal.data.service.DataWorkOrderService;
import com.kingint.web.portal.serve.service.ActivitiCancelService;
import com.kingint.web.portal.serve.service.DepartmentRepairService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kingint.web.sys.service.UmsAdminService;
import com.kingint.web.util.CharUtil;
import com.kingint.web.util.WorkType;
import com.kingint.web.util.WorkTypeUtil;
import com.kingint.web.util.spring.SpringContextHolder;
import com.kingint.web.vo.CountParam;
import com.kingint.web.vo.RepairBean;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门保修表 服务实现类
 * </p>
 *
 * @author wxh
 * @since 2020-12-20
 */
@Service
@Slf4j
public class DepartmentRepairServiceImpl extends ServiceImpl<SerDepartmentRepairMapper, SerDepartmentRepair> implements DepartmentRepairService {

    @Resource
    private UmsAdminService adminService;
    @Resource
    private SerWorkOrderMapper workOrderMapper;
    @Resource
    private SerDepartmentRepairMapper departmentRepairMapper;
    @Resource
    private SerDepartmentRepairMiddleMapper departmentRepairMiddleMapper;
    @Resource
    private ActivitiCancelService activitiCancelService;
    @Resource
    private TaskService taskService;
    @Resource
    private BasHotelMapper hotelMapper;
    @Resource
    private UmsMemberMapper memberMapper;
    @Resource
    private RepairBean repairBean;
    @Resource
    private HistoryService historyService;
    @Resource
    private SerDepartmentGoodsLogMapper departmentGoodsLogMapper;
    @Resource
    private SerReceiveWorkMiddleService receiveWorkMiddleService;
    @Resource
    private SerReceiveWorkMiddleMapper receiveWorkMiddleMapper;
    @Resource
    private SerCheckWorkMiddleMapper checkWorkMiddleMapper;
    @Resource
    private WorkOrderTypeService workOrderTypeService;
    @Resource
    private BasOrderTypeHotelTimeService basOrderTypeHotelTimeService;
    @Resource
    private DataWorkOrderService dataWorkOrderService;
    @Resource
    private DataHouseServicesService dataHouseServices;


    @Override
    public int addDepartmentRepairInfo(DepartmentRepairParam departmentRepairParam) {
        UmsMember currentMember = adminService.getCurrentMember();//当前用户
        //相关工单添加在总表中
        SerWorkOrder workOrder = new SerWorkOrder();//总表
        BeanUtils.copyProperties(departmentRepairParam, workOrder);
        workOrder.setHotelId(currentMember.getHotelId());
        workOrder.setSubmitUserId(currentMember.getId());//提交人员
        workOrder.setWorkTypeId(WorkTypeUtil.getWorkTypeIdByName(WorkType.repairName));//对应的工单类型怎么查询出来

        workOrder.setCreateTime(new Date());
        workOrder.setWorkOrderStatus(0);//订单类型普通
        workOrder.setOrderSn(CharUtil.generateOrderSn());//工单号
        int insert = workOrderMapper.insert(workOrder);//插入相关的保修信息
        String businessKey = repairBean.getProcessInstanceKey() + "_" + currentMember.getHotelId() + "_" + workOrder.getId();//业务相关参数

        //同时创建部门保修表
        SerDepartmentRepair repair = new SerDepartmentRepair();
        BeanUtils.copyProperties(departmentRepairParam, repair);//拷贝信息
        repair.setWorkId(workOrder.getId());
        //保修物品信息
        List<BasWarrantyItems> warrantyItemsList = departmentRepairParam.getWarrantyItemsList();
        Object o = JSONObject.toJSON(warrantyItemsList);//转换为json
        repair.setWarrantyContent(o.toString());
        repair.setCreateTime(new Date());

        //确定检查人员，查询当前人员部门的经理
        List<MemberReturn> manager = memberMapper.getDepartmentManager(currentMember.getDepartmentId(), "经理");
        if (!CollectionUtils.isEmpty(manager)) {
            repair.setCheckUserId(manager.get(0).getId());

            //同时添加工单与检查人员中间表 ser_check_work_middle
            SerCheckWorkMiddle middle = new SerCheckWorkMiddle();
            middle.setCheckUserId(manager.get(0).getId());
            middle.setCreateTime(new Date());
            middle.setWorkId(workOrder.getId());
            checkWorkMiddleMapper.insert(middle);
        } else {
            log.debug("当前部门没有经理");
            return -1;
        }
        //添加信息
        departmentRepairMapper.insert(repair);
        //同时activiti定义中的流程启动
        HashMap<String, Object> variables = new HashMap<>();
        variables.put(repairBean.getCreateNameEl(), currentMember.getUsername());//下一步流程执行人
        //流程实例id
        String processInstanceId = activitiCancelService.startProcess(repairBean.getProcessInstanceKey(), businessKey, variables);
        //更新流程实例id
        workOrder.setProcessInstanceId(processInstanceId);
        workOrder.setOrderStatus(1);
        workOrderMapper.updateById(workOrder);

        //工单上报计时
        basOrderTypeHotelTimeService.addtim(currentMember.getHotelId(), workOrder.getId(), WorkType.repairName,new Date().getTime());

        //住客统计
        dataHouseServices.addDataHouseInfo(currentMember.getHotelId(),CountParam.DEPARTMENTREPAIRCOUNT, workOrder.getRoomId(), workOrder.getRoomNum());

        //总工单统计
        dataWorkOrderService.addwork(currentMember.getHotelId(),CountParam.DEPARTMENTREPAIRCOUNT);
        return insert;
    }

    /**
     * 维修接单
     */
    @Override
    public Integer receiveOrder(Integer id) {
        UmsMember currentMember = adminService.getCurrentMember();

        SerDepartmentRepair repair = departmentRepairMapper.selectById(id);
        //添加中间表 ser_receive_work_middle 维修人员接受
        SerReceiveWorkMiddle middle = new SerReceiveWorkMiddle();
        middle.setWorkId(repair.getWorkId());
        middle.setReceiveUserId(currentMember.getId());
        receiveWorkMiddleService.insertReceiveWorkInfo(middle);


        //添加部门维修与维修人员中间表
        SerDepartmentRepairMiddle repairMiddle = new SerDepartmentRepairMiddle();
        repairMiddle.setCreateTime(new Date());
        repairMiddle.setDepartmentRepairId(repair.getId());
        repairMiddle.setRepairUserId(currentMember.getId());
        departmentRepairMiddleMapper.insert(repairMiddle);


        SerWorkOrder serWorkOrder = workOrderMapper.selectById(repair.getWorkId());

        //查询对应的businessKey的流程实例
        Task task = taskService.createTaskQuery()
                .processInstanceId(serWorkOrder.getProcessInstanceId())
                .singleResult();
        if (!StringUtils.isEmpty(task)) {
            HashMap<String, Object> map = new HashMap<>();
            map.put(repairBean.getReceiveStatus(), 1);//确定状态
            map.put(repairBean.getReceiveNameEl(), currentMember.getUsername());//下一阶段处理人
            taskService.complete(task.getId(),map);
            return 1;
        }
        log.debug("没有查询到相关的任务流程");
        return 0;
    }

    /**
     * 获取酒店待接单的维修单
     *
     * @return
     */
    @Override
    public List<DepartmentRepairFront> getWaitReceiveOrder() {
        UmsMember currentMember = adminService.getCurrentMember();
        Integer hotelId = currentMember.getHotelId();//对应的酒店id
        if (StringUtils.isEmpty(hotelId)) {
            log.debug("当前用户账号没有关联酒店id");
            return null;
        }
        //查询总单中未接单的维修工单信息
        Integer workTyId = WorkTypeUtil.getWorkTypeIdByName(WorkType.repairName);//对应工单id
        List<DepartmentRepairFront> frontRepairList = departmentRepairMapper.getFrontRepairList(hotelId, workTyId, 1);
        return frontRepairList;
    }


    @Override
    public DepartmentRepairParam getDepartmentRepairOrderDetails(Integer workId) {
        DepartmentRepairParam repairById = departmentRepairMapper.getDepartmentRepairById(workId);
        //获取对应酒店名称
        BasHotel basHotel = hotelMapper.selectById(repairById.getHotelId());
        repairById.setHotelName(basHotel.getName());
        //获取处理人
        UmsMember member = memberMapper.selectById(repairById.getSubmitUserId());
        repairById.setSubmitUserName(member.getUsername());
        //进行详情的处理
        String warrantyContent = repairById.getWarrantyContent();
        if (!StringUtils.isEmpty(warrantyContent)) { //保修物品json转为list集合
            List<BasWarrantyItems> items = JSONObject.parseArray(warrantyContent, BasWarrantyItems.class);
            repairById.setWarrantyItemsList(items);
        }
        String repairGoods = repairById.getRepairGoods();
        if (!StringUtils.isEmpty(repairGoods)) { //维修耗材json转为list集合
            List<BasRepairGoods> goods = JSONObject.parseArray(repairGoods, BasRepairGoods.class);
            repairById.setRepairGoodsList(goods);
        }
        //查询判是否有维修人员中间表
        QueryWrapper<SerDepartmentRepairMiddle> wrapper = new QueryWrapper<>();
        wrapper.eq("department_repair_id", repairById.getRepairId())
                .eq("status",0);
        List<SerDepartmentRepairMiddle> middles = departmentRepairMiddleMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(middles)) {
            List<MemberReturn> memberList = new ArrayList<>();
            middles.stream().forEach(s -> {
                MemberReturn memberInfoById = memberMapper.getMemberInfoById(s.getRepairUserId());
                memberList.add(memberInfoById);
            });
            repairById.setMemberList(memberList);
        }
        //查询处理进度
        String instanceId = repairById.getProcessInstanceId();
        if (!StringUtils.isEmpty(instanceId)) {
            List<StepBean> activityInstance = getActivityInstance(instanceId);
            repairById.setStepBeans(activityInstance);
        }
        return repairById;
    }

    /**
     * 获取流程实例处理流程
     *
     * @param instanceId
     */
    private List<StepBean> getActivityInstance(String instanceId) {
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceId)
                .orderByHistoricActivityInstanceStartTime().desc()
                .list();
        List<StepBean> stepBeans = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {//不为空
            for (HistoricActivityInstance info : list) {
                String activityName = info.getActivityName();
                if (activityName.equals("挂起网关"))
                    break;
                if (activityName.equals("StartEvent"))
                    continue;
                if (activityName.equals("EndEvent"))
                    continue;
                String assignee = info.getAssignee();//执行人
                StepBean stepBean = new StepBean();
                stepBean.setStartTime(info.getStartTime());
                stepBean.setStepContent(activityName + " " + assignee);
                stepBeans.add(stepBean);
            }
        }
        return stepBeans;
    }

    @Override
    public int finishDepartmentRepairOrder(DepartmentRepairParam departmentRepairParam) {
        UmsMember currentMember = adminService.getCurrentMember();
        List<MemberReturn> memberList = departmentRepairParam.getMemberList();
        Long checkUserId = departmentRepairParam.getCheckUserId();//验收人员
        UmsMember umsMember = memberMapper.selectById(checkUserId);

        SerWorkOrder serWorkOrder = workOrderMapper.selectById(departmentRepairParam.getWorkId());

        //添加部门维修与维修人员中间表
        Integer repairId = departmentRepairParam.getRepairId();//维修单id
        memberList.stream().forEach(s->{
            QueryWrapper<SerDepartmentRepairMiddle> wrapper = new QueryWrapper<>();
            wrapper.eq("department_repair_id",repairId)
                    .eq("repair_user_id",s.getId())
                    .eq("status",0);
            Integer integer = departmentRepairMiddleMapper.selectCount(wrapper);
            if(integer==0){
                SerDepartmentRepairMiddle middle = new SerDepartmentRepairMiddle();
                middle.setCreateTime(new Date());
                middle.setDepartmentRepairId(repairId);
                middle.setRepairUserId(s.getId());
                departmentRepairMiddleMapper.insert(middle);
            }
        });

        //将维修耗材转化为json
        List<BasRepairGoods> repairGoodsList = departmentRepairParam.getRepairGoodsList();
        if (!CollectionUtils.isEmpty(repairGoodsList)) {
            Object o = JSONObject.toJSON(repairGoodsList);
            departmentRepairParam.setRepairGoods(o.toString());
            //记录维修物品的出库记录
            repairGoodsList.stream().forEach(s->{
                SerDepartmentGoodsLog log = new SerDepartmentGoodsLog();
                log.setCreateTime(new Date());
                log.setDepartmentRepairId(departmentRepairParam.getRepairId());
                log.setBasRepairGoodsId(s.getId());
                log.setGoodsNum(s.getNumber());
                log.setHotelId(currentMember.getHotelId());
                departmentGoodsLogMapper.insert(log);
            });
        }
        //拷贝相关的数据
        SerDepartmentRepair repair = new SerDepartmentRepair();
        BeanUtils.copyProperties(departmentRepairParam, repair);
        repair.setRepairTime(new Date());
        repair.setId(departmentRepairParam.getRepairId());
        int i = departmentRepairMapper.updateById(repair);

        //同时进行相关流程的进行
        //查询对应的businessKey的流程实例 结束这个流程实例
        Task task = taskService.createTaskQuery()
                .processDefinitionKey(repairBean.getProcessInstanceKey())
                .processInstanceId(serWorkOrder.getProcessInstanceId())
                .singleResult();
        if (!StringUtils.isEmpty(task)) {
            log.info("完成提加节点，进行下一个节点");
            HashMap<String, Object> map = new HashMap<>();
            map.put(repairBean.getCompleteStatus(), 1);//完成状态
            map.put(repairBean.getCheckNameEl(), umsMember.getUsername());
            taskService.setVariables(task.getId(), map);
            taskService.complete(task.getId());
            basOrderTypeHotelTimeService.deltim(currentMember.getHotelId(),departmentRepairParam.getWorkId(),WorkType.repairName);
            workOrderTypeService.judgeWorkOrderIsTimeOut(currentMember.getId(), departmentRepairParam.getWorkId(), WorkType.repairName);
        }
        return i;
    }

    //获取所有处理中的维修单
    @Override
    public List<DepartmentRepairFront> getUserHandleRepairOrder() {
        UmsMember currentMember = adminService.getCurrentMember();
        Integer hotelId = currentMember.getHotelId();//对应的酒店id
        if (StringUtils.isEmpty(hotelId)) {
            log.debug("当前用户账号没有关联酒店id");
            return null;
        }
        Integer workTyId = WorkTypeUtil.getWorkTypeIdByName(WorkType.repairName);//对应工单id
        List<DepartmentRepairFront> departmentList = departmentRepairMapper.getUserRepairList(hotelId, workTyId, 2, currentMember.getId());
        return departmentList;
    }

    @Override
    public List<DepartmentRepairFront> getAlreadyCompleted() {
        UmsMember currentMember = adminService.getCurrentMember();
        Integer hotelId = currentMember.getHotelId();//对应的酒店id
        if (StringUtils.isEmpty(hotelId)) {
            log.debug("当前用户账号没有关联酒店id");
            return null;
        }
        Integer workTyId = WorkTypeUtil.getWorkTypeIdByName(WorkType.repairName);//对应工单id
        List<DepartmentRepairFront> departmentList = departmentRepairMapper.getUserRepairList(hotelId, workTyId, 5, currentMember.getId());
        return departmentList;
    }

    /**
     * 查询用户待验收的
     *
     * @return
     */
    @Override
    public List<DepartmentRepairFront> getUserWaitCheckOrder() {
        UmsMember currentMember = adminService.getCurrentMember();
        Integer hotelId = currentMember.getHotelId();//对应的酒店id
        if (StringUtils.isEmpty(hotelId)) {
            log.debug("当前用户账号没有关联酒店id");
            return null;
        }
        Integer workTyId = WorkTypeUtil.getWorkTypeIdByName(WorkType.repairName);//对应工单id
        List<DepartmentRepairFront> departmentList = departmentRepairMapper.getUserRepairList(hotelId, workTyId, 3, currentMember.getId());
        return departmentList;
    }

    @Override
    public List<MemberReturn> getRepairUserList() {
        UmsMember currentMember = adminService.getCurrentMember();
        Integer hotelId = currentMember.getHotelId();//对应的酒店id
        if (StringUtils.isEmpty(hotelId)) {
            log.debug("当前用户账号没有关联酒店id");
            return null;
        }
        List<MemberReturn> departmentUser = memberMapper.getDepartmentUser(currentMember.getDepartmentId(), 1);
        return departmentUser;
    }

    @Override
    public Integer completeRepairInfo(Integer status, Integer id) {
        SerWorkOrder serWorkOrder = workOrderMapper.selectById(id);
        Task task = taskService.createTaskQuery()
                .processInstanceId(serWorkOrder.getProcessInstanceId())
                .singleResult();
        if(!StringUtils.isEmpty(task)){
            Map<String,Object> map=new HashMap<>();
            map.put(repairBean.getRejectStatus(),status);
            taskService.setVariables(task.getId(),map);
            taskService.complete(task.getId());
            return 1;
        }
        return 0;
    }
}
